package com.zrc.superframe_net.common.net

import com.google.gson.GsonBuilder
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.lxj.xpopup.impl.LoadingPopupView
import com.lxj.xpopup.interfaces.SimpleCallback
import com.zrc.superframe_net.interfac.NetBase
import com.zrc.superframe_net.common.CacheConfig
import com.zrc.superframe_net.common.net.Net.Companion.client
import com.zrc.superframe_net.common.LoadingConfig
import com.zrc.superframe_net.room.NetRoomUtil
import com.zrc.superframe_net.utils.NetUtils
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import okhttp3.ResponseBody

/**
 * @Author: superman
 * @CreateTime: 6/27/21
 * @Describe:带进度条的 subscriber
 */
class NetObserver<T>(
    private val page: NetBase? = null,//基类，需要基层 BaseFragment/BaseActivity   因为里面有做资源回收 -> 比如Activity退出时，取消队列
    private val loadingConfig: LoadingConfig? = null, //dilog配置
    private val cacheConfig: CacheConfig? = null, //缓存配置
    private var callback: BaseNetCallBack<T>? = null
) : Observer<T> {
    var disposable: Disposable? = null//开关
    private var mCustomProgress: LoadingPopupView? = null//进度条Dialog

    init {
        initDialog()
    }

    override fun onSubscribe(d: Disposable) {
        callback?.onSubscribe(d)
        disposable = d
        kotlin.run {
            cacheConfig?.let {
                val resulteBy = queryResulteBy(it.tag)//有网络有缓存  不进行网络请求，直接从本地取
                if (!resulteBy.isNullOrEmpty()) {
                    d.dispose()
                    try {
                        callback?.onCookieSucceed(resulteBy, it.tag)
                    } catch (e: Exception) {
                        NetRoomUtil.database.netCacheDao().find(it.tag)?.let {
                            NetRoomUtil.database.netCacheDao().delete(it)
                        }
                    }
                    return@run
                }
            }
            page?.let {
                if (!it.addRequestQueue(d)) { //添加失败就关闭网络请求
                    d.dispose()
                }
            }
            showProgressDialog() //显示进度条
        }
    }

    override fun onNext(t: T) {
        if (cacheConfig != null) {
            callback?.onSucceed(t, cacheConfig.tag) //回调
            if (cacheConfig.cache && t !is ResponseBody) {//如果需要缓存处理 ResponseBody 需要自己去存储
                updateResulteBy(cacheConfig.tag, t)//保存到数据库
            }
        } else {
            callback?.onSucceed(t, "") //回调
        }
    }

    override fun onError(e: Throwable) {
        callback?.onError(e)
        dismissProgressDialog()
        gc()
    }

    override fun onComplete() {
        callback?.onComplete()
        dismissProgressDialog()
        gc()
    }

    //线程异常，或者成功后，调用回收
    private fun gc() {
        disposable?.let {
            page?.removeRequestQueue(it)
        }
        disposable = null
        mCustomProgress = null
        callback = null
    }

    //显示进度条
    private fun initDialog() {
        loadingConfig?.let {
            if (it.show) {
                mCustomProgress = XPopup.Builder(it.context)
                    .dismissOnBackPressed(it.cancel)
                    .dismissOnTouchOutside(it.cancel)
                    .setPopupCallback(object : SimpleCallback() {
                        override fun onDismiss(popupView: BasePopupView) {
                            super.onDismiss(popupView)
                            onCancelProgress()
                        }
                    })
                    .asLoading("加载中")
            }
        }
    }

    //显示加载Dialog
    private fun showProgressDialog() {
        mCustomProgress?.show()
    }

    //销毁加载Dialog
    private fun dismissProgressDialog() {
        mCustomProgress?.let {
            if (it.isShow) {
                it.dismiss()
            }
        }
    }

    //取消ProgressDialog的时候，取消对observable的订阅，同时也取消了http请求
    private fun onCancelProgress() {
        disposable?.let {
            if (!it.isDisposed) {
                it.dispose()
            }
        }
        gc()
    }

    /**
     * 查询缓存数据
     * @param tag          缓存时候的标识，一般是接口名/自定义
     * @return  有就返回String 超时或者无缓存返回 null
     */
    private fun queryResulteBy(tag: String): String? {
        cacheConfig?.let {
            if (it.cacheTime == 0) {//没有设置 添加默认缓存时间
                if (!NetUtils.instance.isNetworkAvailable()) {
                    it.cacheTime = client().mBuilder.noNetBufferTime //无网络的时候,取无网络 超时时间
                } else {
                    it.cacheTime = client().mBuilder.netBufferTime //有网情况下的本地缓存时间默认60秒
                }
            } else {
                if (!NetUtils.instance.isNetworkAvailable()) {
                    it.cacheTime = client().mBuilder.noNetBufferTime //无网络的时候,取无网络 超时时间
                }
            }

            val resulte = NetRoomUtil.database.netCacheDao().find(tag)//读取数据库
            if (resulte != null) {
                val time = (System.currentTimeMillis() - resulte.time) / 1000
                if (time < it.cacheTime) {
                    return resulte.gson
                } else {
                    NetRoomUtil.database.netCacheDao().delete(resulte)
                }
            }
        }
        return null
    }

    /**
     * 更新缓存数据
     * @param t 需要缓存的类
     */
    private fun updateResulteBy(tag: String, t: T) {
        NetRoomUtil.database.netCacheDao().update(tag, GsonBuilder().create().toJson(t))
    }
}